// IPFS + MyNFT 部署示例脚本
// 基于您的IPFS文件夹结构

const { ethers } = require('ethers');
require('dotenv').config();

// 基于您的IPFS文件结构的配置
const IPFS_CONFIG = {
    // 您的IPFS文件夹hash (上传后替换为实际hash)
    folderHash: "QmYP7zPrdxLPeJ4h3YghxYZ7YYn3dYjF1R25TxfG9cG3jn",

    // 您的NFT文件列表
    nftFiles: [
        "myNFT1.jpeg",
        "myNFT2.jpeg",
        "myNFT3.jpeg",
        "myNFT4.jpeg",
        "myNFT5.jpeg"
    ],

    // 网络配置
    rpcUrl: process.env.SEPOLIA_RPC_URL,
    privateKey: process.env.PRIVATE_KEY
};

// 部署配置
const DEPLOY_CONFIG = {
    name: "MyLearningNFT",
    symbol: "MLN",
    baseURI: `ipfs://${IPFS_CONFIG.folderHash}/`, // 使用您的IPFS hash
    maxSupply: 1000,
    maxMintPerAddress: 10
};

// 合约ABI (简化版)
const CONTRACT_ABI = [
    "constructor(string memory _name, string memory _symbol, string memory _initialBaseURI, uint256 _maxSupply, uint256 _maxMintPerAddress)",
    "function name() public view returns (string)",
    "function symbol() public view returns (string)",
    "function totalSupply() public view returns (uint256)",
    "function owner() public view returns (address)",
    "function baseURI() public view returns (string)",
    "function mintNFT(address to, string memory _tokenURI) public payable returns (uint256)",
    "function tokenURI(uint256 tokenId) public view returns (string)",
    "function ownerOf(uint256 tokenId) public view returns (address)",
    "function balanceOf(address owner) public view returns (uint256)",
    "function tokensOfOwner(address owner) public view returns (uint256[])",
    "event NFTMinted(address indexed to, uint256 indexed tokenId, string tokenURI)"
];

// 合约字节码 - 请替换为实际编译后的字节码
const CONTRACT_BYTECODE = `
请将编译后的MyNFT.sol字节码粘贴到这里
使用命令: npx solc --bin --include-path node_modules --base-path . MyNFT.sol
`;

async function deployWithIPFS() {
    try {
        console.log("🚀 开始部署MyNFT合约 (使用IPFS)...\n");

        // 检查环境变量
        if (!IPFS_CONFIG.privateKey) {
            throw new Error("❌ 请设置PRIVATE_KEY环境变量");
        }

        // 连接网络
        const provider = new ethers.providers.JsonRpcProvider(IPFS_CONFIG.rpcUrl);
        const wallet = new ethers.Wallet(IPFS_CONFIG.privateKey, provider);

        console.log("📡 网络信息:");
        console.log("- 网络:", (await provider.getNetwork()).name);
        console.log("- 部署地址:", wallet.address);
        console.log("- 余额:", ethers.utils.formatEther(await wallet.getBalance()), "ETH\n");

        // 显示IPFS配置
        console.log("📁 IPFS配置:");
        console.log("- 文件夹Hash:", IPFS_CONFIG.folderHash);
        console.log("- 基础URI:", DEPLOY_CONFIG.baseURI);
        console.log("- NFT文件数量:", IPFS_CONFIG.nftFiles.length);
        console.log("- 文件列表:", IPFS_CONFIG.nftFiles.join(", "), "\n");

        // 检查字节码
        if (CONTRACT_BYTECODE.includes("请将编译后的")) {
            console.log("⚠️  请先编译合约并更新字节码！");
            console.log("运行命令: npx solc --bin --include-path node_modules --base-path . MyNFT.sol");
            return;
        }

        // 创建合约工厂
        const contractFactory = new ethers.ContractFactory(
            CONTRACT_ABI,
            CONTRACT_BYTECODE,
            wallet
        );

        console.log("🎨 部署参数:");
        console.log("- 名称:", DEPLOY_CONFIG.name);
        console.log("- 符号:", DEPLOY_CONFIG.symbol);
        console.log("- 基础URI:", DEPLOY_CONFIG.baseURI);
        console.log("- 最大供应量:", DEPLOY_CONFIG.maxSupply);
        console.log("- 每地址最大铸造:", DEPLOY_CONFIG.maxMintPerAddress, "\n");

        // 部署合约
        console.log("⏳ 正在部署合约...");
        const contract = await contractFactory.deploy(
            DEPLOY_CONFIG.name,
            DEPLOY_CONFIG.symbol,
            DEPLOY_CONFIG.baseURI,
            DEPLOY_CONFIG.maxSupply,
            DEPLOY_CONFIG.maxMintPerAddress,
            {
                gasLimit: 5000000,
                gasPrice: ethers.utils.parseUnits('20', 'gwei')
            }
        );

        console.log("🔄 等待交易确认...");
        console.log("- 交易哈希:", contract.deployTransaction.hash);

        await contract.deployed();

        console.log("\n✅ 合约部署成功!");
        console.log("- 合约地址:", contract.address);
        console.log("- 区块号:", contract.deployTransaction.blockNumber);

        // 验证部署
        console.log("\n🔍 验证合约信息:");
        const name = await contract.name();
        const symbol = await contract.symbol();
        const totalSupply = await contract.totalSupply();
        const owner = await contract.owner();
        const baseURI = await contract.baseURI();

        console.log("- NFT名称:", name);
        console.log("- NFT符号:", symbol);
        console.log("- 当前供应量:", totalSupply.toString());
        console.log("- 合约所有者:", owner);
        console.log("- 基础URI:", baseURI);

        // 保存部署信息
        const deploymentInfo = {
            contractAddress: contract.address,
            deploymentHash: contract.deployTransaction.hash,
            deploymentBlock: contract.deployTransaction.blockNumber,
            deployer: wallet.address,
            network: "sepolia",
            timestamp: new Date().toISOString(),
            ipfsConfig: IPFS_CONFIG,
            deployConfig: DEPLOY_CONFIG
        };

        require('fs').writeFileSync(
            'ipfs-deployment-info.json',
            JSON.stringify(deploymentInfo, null, 2)
        );

        console.log("\n📄 部署信息已保存到 ipfs-deployment-info.json");

        // 生成链接
        console.log("\n🔗 相关链接:");
        console.log("- Etherscan:", `https://sepolia.etherscan.io/address/${contract.address}`);
        console.log("- OpenSea:", `https://testnets.opensea.io/assets/sepolia/${contract.address}`);

        console.log("\n🎉 部署完成！现在可以铸造NFT了！");

        return contract;

    } catch (error) {
        console.error("❌ 部署失败:", error.message);
        throw error;
    }
}

// 铸造所有NFT的示例函数
async function mintAllNFTs(contractAddress) {
    try {
        console.log("\n🎨 开始铸造所有NFT...");

        const provider = new ethers.providers.JsonRpcProvider(IPFS_CONFIG.rpcUrl);
        const wallet = new ethers.Wallet(IPFS_CONFIG.privateKey, provider);
        const contract = new ethers.Contract(contractAddress, CONTRACT_ABI, wallet);

        const mintedTokens = [];

        for (let i = 0; i < IPFS_CONFIG.nftFiles.length; i++) {
            const fileName = IPFS_CONFIG.nftFiles[i];
            const tokenNumber = i + 1;

            console.log(`\n🎨 铸造NFT ${tokenNumber}/${IPFS_CONFIG.nftFiles.length}:`);
            console.log("- 文件:", fileName);

            try {
                const tx = await contract.mintNFT(wallet.address, fileName);
                const receipt = await tx.wait();

                const mintEvent = receipt.events?.find(e => e.event === 'NFTMinted');
                const tokenId = mintEvent?.args?.tokenId;

                console.log("✅ 铸造成功");
                console.log("   - Token ID:", tokenId.toString());
                console.log("   - 交易哈希:", tx.hash);

                // 验证URI
                const tokenURI = await contract.tokenURI(tokenId);
                console.log("   - Token URI:", tokenURI);

                mintedTokens.push({
                    tokenId: tokenId.toString(),
                    fileName: fileName,
                    tokenURI: tokenURI
                });

            } catch (error) {
                console.log("❌ 铸造失败:", error.message);
            }
        }

        console.log("\n📊 铸造结果总结:");
        console.log("- 成功铸造:", mintedTokens.length, "个NFT");
        console.log("- 失败:", IPFS_CONFIG.nftFiles.length - mintedTokens.length, "个NFT");

        if (mintedTokens.length > 0) {
            console.log("\n🎉 成功铸造的NFT:");
            mintedTokens.forEach((token, index) => {
                console.log(`${index + 1}. Token ID: ${token.tokenId}, 文件: ${token.fileName}`);
                console.log(`   URI: ${token.tokenURI}`);
                console.log(`   OpenSea: https://testnets.opensea.io/assets/sepolia/${contractAddress}/${token.tokenId}`);
            });
        }

        return mintedTokens;

    } catch (error) {
        console.error("❌ 铸造过程失败:", error.message);
    }
}

// 验证IPFS访问的函数
async function verifyIPFSAccess() {
    console.log("\n🔍 验证IPFS访问...");

    const baseURL = `https://ipfs.io/ipfs/${IPFS_CONFIG.folderHash}`;

    console.log("📁 IPFS文件夹访问:");
    console.log("- 文件夹URL:", baseURL);

    console.log("\n🖼️  单个文件访问:");
    IPFS_CONFIG.nftFiles.forEach((fileName, index) => {
        const fileURL = `${baseURL}/${fileName}`;
        console.log(`${index + 1}. ${fileName}: ${fileURL}`);
    });

    console.log("\n💡 请手动访问这些链接验证文件是否可访问");
}

// 主函数
async function main() {
    const args = process.argv.slice(2);

    if (args[0] === 'verify') {
        // 验证IPFS访问
        await verifyIPFSAccess();
    } else if (args[0] === 'mint' && args[1]) {
        // 铸造NFT
        await mintAllNFTs(args[1]);
    } else {
        // 部署合约
        const contract = await deployWithIPFS();
        if (contract) {
            console.log("\n💡 下一步操作:");
            console.log("1. 验证IPFS访问: node ipfs-deploy-example.js verify");
            console.log(`2. 铸造所有NFT: node ipfs-deploy-example.js mint ${contract.address}`);
        }
    }
}

// 运行脚本
if (require.main === module) {
    main().catch(console.error);
}

module.exports = { deployWithIPFS, mintAllNFTs, verifyIPFSAccess, IPFS_CONFIG };
